package com.example.demo.debounce;

import java.util.concurrent.*;

/**
 * 抖动函数
 * 以 相同 key 在 delay 时间内如果重复调用本方法将只会调用最后一次
 */
public class Debounce {

    private static final ScheduledExecutorService SCHEDULE = Executors.newSingleThreadScheduledExecutor();

    private static final ConcurrentHashMap<Object, Future<?>> DELAYED_MAP = new ConcurrentHashMap<>();

    public static void debounce(final Object key, final Runnable runnable, long delay, TimeUnit unit) {
        //put方法在key相同时，会用新的value覆盖掉旧的value，并返回旧的value值。
        final Future<?> prev = DELAYED_MAP.put(key, SCHEDULE.schedule(() -> {
            try {
                runnable.run();
            } finally {
                DELAYED_MAP.remove(key);
            }
        }, delay, unit));
        if (prev != null) {
            //尝试取消此任务
            prev.cancel(true);
        }
    }

    public static void shutdown() {
        SCHEDULE.shutdownNow();
    }

    public static void main(String[] args) {
        Debounce.debounce("1", () -> {System.out.println(11);}, 3, TimeUnit.SECONDS);
        Debounce.debounce("1", () -> {System.out.println(22);}, 3, TimeUnit.SECONDS);

        Debounce.debounce("2", () -> {System.out.println(44);}, 3, TimeUnit.SECONDS);
        Debounce.debounce("2", () -> {System.out.println(44);}, 3, TimeUnit.SECONDS);
        Debounce.debounce("2", () -> {System.out.println(44);}, 3, TimeUnit.SECONDS);

        Debounce.debounce("1", () -> {System.out.println(33);}, 3, TimeUnit.SECONDS);
    }

}
